package com.ruoyi.common.utils;

import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import io.minio.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;

/**
 * @author lishi
 * @description: minIO上传工具
 * @date 2021/1/14 14:42
 */
@Component
public class FileUploader {

    @Value("${minIo.endPoint}")
    private String endPoint;
    @Value("${minIo.access_key}")
    private String access_key;
    @Value("${minIo.secret_key}")
    private String secret_key;
    @Value("${minIo.bucket_name}")
    private String bucket_name;

    public String upload(String baseDir, MultipartFile file) {
        try {
            //与通用上传一样，校验一下
            String pathFileName = check(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
            // 使用MinIO服务的URL，端口，Access key和Secret key创建一个MinioClient对象
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(endPoint)
                    .credentials(access_key, secret_key)
                    .build();
            // 检查存储桶是否已经存在
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket_name).build());
            if(isExist) {
                System.out.println("Bucket already exists.");
            } else {
                // 创建一个名为asiatrip的存储桶，用于存储照片的zip文件。
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket_name).build());
            }
            // 使用putObject上传一个文件到存储桶中。
            // 文件的ContentType
            String contentType = file.getContentType();
            String fileName = baseDir.substring(baseDir.indexOf("/") + 1) + pathFileName;
            minioClient.putObject(
                    PutObjectArgs.builder().bucket(bucket_name).object(fileName).stream(
                            file.getInputStream(), -1, ObjectWriteArgs.MIN_MULTIPART_SIZE * 10)
                            .contentType(contentType)
                            .build());
            System.out.println(fileName + " is successfully uploaded to `" + bucket_name +"` bucket.");
            return "/" + bucket_name + "/" + fileName;
        } catch(Exception e) {
            System.out.println("Error occurred: " + e);
            throw new BusinessException("上传出错。");
        }
    }

    public String check(String baseDir, MultipartFile file, String[] allowedExtension){
        int fileNamelength = file.getOriginalFilename().length();
        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH) {
            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
        }
        try {
            FileUploadUtils.assertAllowed(file, allowedExtension);
            String fileName = FileUploadUtils.extractFilename(file);
            return "/" + fileName;
        } catch (Exception e){
            throw new BusinessException("校验出错。");
        }
    }

    /**
     * 以inputStream方式上传
     *
     * @param fileName    文件名
     * @param inputStream 文件流
     */
    public String upload(String fileName, InputStream inputStream) throws Exception {
        // Create a minioClient
        MinioClient minioClient = MinioClient.builder()
                .endpoint(endPoint)
                .credentials(access_key, secret_key)
                .build();
        // Make bucket if not exist.
        boolean found =
                minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket_name).build());
        if (!found) {
            // Make a new bucket called.
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket_name).build());
        } else {
            System.out.println("Bucket " + bucket_name + " already exists.");
        }
        // Upload
        minioClient.putObject(
                PutObjectArgs.builder().bucket(bucket_name).object(fileName).stream(
                        inputStream, -1, ObjectWriteArgs.MIN_MULTIPART_SIZE * 10)
                        .build());
        // Return
        return "/" + bucket_name + "/" + fileName;
    }
}
